package com.acme.bankapp.domain;

import com.acme.bankapp.email.EmailService;
import com.acme.bankapp.exception.ClientExistsException;

import java.io.Serializable;
import java.util.*;


/**
 * Created by Student on 14.11.2014.
 */
public class Bank implements Serializable{
    private HashSet<Client> clients = new HashSet<>();
    transient final private int countListener = 3;
    transient public ClientRegistrationListener[] listeners = new ClientRegistrationListener[countListener];

    public Bank() {
        listeners[2] = new EmailNotificationListener();

        listeners[0] = new ClientRegistrationListener() {
            @Override
            public void onClientAdded(Client c) {
                if( !isClosed() ){
                    System.out.println(c.getClientSalutation());
                }
            }
        };

        listeners[1] = new ClientRegistrationListener(){
            @Override
            public void onClientAdded(Client c) {
                if( !isClosed() ){
                    System.out.println( c.getClientSalutation() + ": " + new Date());
                }
            }
        };
    }

    public void addClient (Client client) {
        try {
            for (Client c : clients) {
                if (c.getName().equals(client.getName())) {
                    throw new ClientExistsException(client.getName());
                }
            }

            clients.add(client);
            this.onClientAdded(client);

        }catch (ClientExistsException e){
            System.out.println(e);
        }
    }

    public Set<Client> getClients() {
        return Collections.unmodifiableSet(clients);
    }

    public int getClientsCount() {
        return clients.size();
    }

    public void onClientAdded(Client client) {
        for( int i = 0; i < countListener; i++ ) {
            if( listeners[i] != null) {
                listeners[i].onClientAdded(client);
            }
        }
    }

    public void closeListeners(){
        for( int i = 0; i < countListener; i++ ) {
            if( listeners[i] != null ) {
                listeners[i].close();
            }
        }

    }

    abstract class ClientRegistrationListener{
        boolean closed = false;

        abstract void onClientAdded(Client c);

        public void close(){
            closed = true;
        }

        boolean isClosed(){
            return closed;
        }
    }

    class EmailNotificationListener extends ClientRegistrationListener{
        public EmailService emailService = new EmailService();

        @Override
        public void onClientAdded(Client client) {
            try {
                emailService.addEmail(client, "address");
            } catch (Exception e) {
                System.out.println(e);
            }
        }

        @Override
        public void close(){
            super.close();
            emailService.close();
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Bank bank = (Bank) o;

        if (countListener != bank.countListener) return false;
        if (clients != null ? !clients.equals(bank.clients) : bank.clients != null) return false;
        if (!Arrays.equals(listeners, bank.listeners)) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = clients != null ? clients.hashCode() : 0;
        result = 31 * result + countListener;
        result = 31 * result + (listeners != null ? Arrays.hashCode(listeners) : 0);
        return result;
    }
}
